package com.jackykeke.opengldemo

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.opengl.GLSurfaceView
import android.os.Bundle
import android.view.*
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.OrientationHelper
import com.jackykeke.opengldemo.ndkutils.MyGLSurfaceView
import com.jackykeke.opengldemo.ndkutils.MyGLSurfaceView.IMAGE_FORMAT_RGBA
import com.jackykeke.opengldemo.ndkutils.MyRecyclerViewAdapter
import com.jackykeke.opengldemo.renderer.MyGLRender
import com.jackykeke.opengldemo.renderer.MyNativeRender.*
import kotlinx.android.synthetic.main.activity_ndk_opengl.*
import kotlinx.android.synthetic.main.sample_selected_layout.*
import java.io.IOException
import java.nio.ByteBuffer

class NdkOpenGLActivity : AppCompatActivity(), ViewTreeObserver.OnGlobalLayoutListener,
    SensorEventListener {

//    private var mSampleSelectedIndex = SAMPLE_TYPE_KEY_BEATING_HEART - SAMPLE_TYPE;

    private var mSampleSelectedIndex = SAMPLE_TYPE_KEY_BIG_EYES - SAMPLE_TYPE;


    private var mGLSurfaceView: MyGLSurfaceView? = null

    private lateinit var mSensorManager: SensorManager

    private val mGLRender: MyGLRender = MyGLRender()

    private val REQUEST_PERMISSIONS = arrayOf(
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.RECORD_AUDIO
    )
    private val PERMISSION_REQUEST_CODE = 1

    private val SAMPLE_TITLES = arrayOf(
//        "DrawTriangle",
//        "TextureMap",
//        "YUV Rendering",
//        "VAO&VBO",
//        "FBO Offscreen Rendering",
//        "EGL Background Rendering",
//        "FBO Stretching",
//        "Coordinate System",
//        "Basic Lighting",
//        "Transform Feedback",
//        "Complex Lighting",
//        "Depth Testing",
//        "Instancing",
//        "Stencil Testing",
//        "Blending",
//        "Particles",
//        "SkyBox",
//        "Assimp Load 3D Model",
//        "PBO",
//        "Beating Heart",
//        "Cloud",
//        "Time Tunnel",
//        "Bezier Curve",
//        "Big Eyes",
//        "Face Slender",
//        "Big Head",
//        "Rotary Head",
//        "Visualize Audio",
//        "Scratch Card",
//        "3D Avatar",
//        "Shock Wave",
//        "MRT",
//        "FBO Blit"


        "Big Eyes",
        "Face Slender"
    )


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_ndk_opengl)


        rootView.viewTreeObserver.addOnGlobalLayoutListener(this)
        mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mGLRender.init()
    }

    override fun onGlobalLayout() {

        rootView.viewTreeObserver.removeOnGlobalLayoutListener(this)

        mGLSurfaceView = MyGLSurfaceView(this, mGLRender)
        val lp = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
        )
        lp.addRule(RelativeLayout.CENTER_IN_PARENT)
        rootView.addView(mGLSurfaceView, lp)
        mGLSurfaceView?.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY)


    }


    override fun onResume() {
        super.onResume()
        mSensorManager.registerListener(
            this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),
            SensorManager.SENSOR_DELAY_FASTEST
        )
        if (!hasPermissionsGranted(REQUEST_PERMISSIONS)) {
            ActivityCompat.requestPermissions(
                this,
                REQUEST_PERMISSIONS,
                PERMISSION_REQUEST_CODE
            )
        }
//        CommonUtils.copyAssetsDirToSDCard(this@MainActivity, "poly", "/sdcard/model")
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return super.onCreateOptionsMenu(menu)

    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {
            R.id.action_change_sample -> {
                showGLSampleDialog()
            }
        }
        return true
    }

    private fun showGLSampleDialog() {

        val dialog = AlertDialog.Builder(this).create()
        val view = LayoutInflater.from(this).inflate(R.layout.sample_selected_layout, null)

        resolution_list_view.layoutManager =
            LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

        val myPreviewSizeViewAdapter = MyRecyclerViewAdapter(
            this,
            listOf(*SAMPLE_TITLES)
        )
        myPreviewSizeViewAdapter.setSelectIndex(mSampleSelectedIndex)
        myPreviewSizeViewAdapter.addOnItemClickListener(object :
            MyRecyclerViewAdapter.OnItemClickListener {
            override fun onItemClick(view: View?, position: Int) {
                rootView.removeView(mGLSurfaceView)
                val lp = RelativeLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
                )
                lp.addRule(RelativeLayout.CENTER_IN_PARENT)
                mGLSurfaceView = MyGLSurfaceView(this@NdkOpenGLActivity, mGLRender)
                rootView.addView(mGLSurfaceView, lp)
                val selectIndex: Int = myPreviewSizeViewAdapter.getSelectIndex()
                myPreviewSizeViewAdapter.setSelectIndex(position)
                myPreviewSizeViewAdapter.notifyItemChanged(selectIndex)
                myPreviewSizeViewAdapter.notifyItemChanged(position)
                mSampleSelectedIndex = position
                mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
                if (rootView.getWidth() != mGLSurfaceView!!.width
                    || rootView.getHeight() != mGLSurfaceView!!.height
                ) {
                    mGLSurfaceView!!.setAspectRatio(rootView.getWidth(), rootView.getHeight())
                }
                mGLRender.setParamsInt(SAMPLE_TYPE, position + SAMPLE_TYPE, 0)
                val sampleType: Int = position + SAMPLE_TYPE
                when (sampleType) {

//                    SAMPLE_TYPE_TRIANGLE -> {
//                    }
//                    SAMPLE_TYPE_TEXTURE_MAP -> loadRGBAImage(R.drawable.dzzz)
//                    SAMPLE_TYPE_YUV_TEXTURE_MAP -> loadNV21Image()
//                    SAMPLE_TYPE_VAO -> {
//                    }
//                    SAMPLE_TYPE_FBO -> loadRGBAImage(R.drawable.java)
//                    SAMPLE_TYPE_FBO_LEG -> loadRGBAImage(R.drawable.leg)
//                    SAMPLE_TYPE_EGL -> startActivity(
//                        Intent(
//                            this@MainActivity,
//                            EGLActivity::class.java
//                        )
//                    )
//                    SAMPLE_TYPE_COORD_SYSTEM, SAMPLE_TYPE_BASIC_LIGHTING, SAMPLE_TYPE_TRANS_FEEDBACK, SAMPLE_TYPE_MULTI_LIGHTS, SAMPLE_TYPE_DEPTH_TESTING, SAMPLE_TYPE_INSTANCING, SAMPLE_TYPE_STENCIL_TESTING -> loadRGBAImage(
//                        R.drawable.board_texture
//                    )
//                    SAMPLE_TYPE_BLENDING -> {
//                        loadRGBAImage(R.drawable.board_texture, 0)
//                        loadRGBAImage(R.drawable.floor, 1)
//                        loadRGBAImage(R.drawable.window, 2)
//                    }
//                    SAMPLE_TYPE_PARTICLES -> {
//                        loadRGBAImage(R.drawable.board_texture)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_SKYBOX -> {
//                        loadRGBAImage(R.drawable.right, 0)
//                        loadRGBAImage(R.drawable.left, 1)
//                        loadRGBAImage(R.drawable.top, 2)
//                        loadRGBAImage(R.drawable.bottom, 3)
//                        loadRGBAImage(R.drawable.back, 4)
//                        loadRGBAImage(R.drawable.front, 5)
//                    }
//                    SAMPLE_TYPE_PBO -> {
//                        loadRGBAImage(R.drawable.front)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_KEY_BEATING_HEART -> mGLSurfaceView!!.renderMode =
//                        GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    SAMPLE_TYPE_KEY_CLOUD -> {
//                        loadRGBAImage(R.drawable.noise)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_KEY_TIME_TUNNEL -> {
//                        loadRGBAImage(R.drawable.front)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_KEY_BEZIER_CURVE ->                         //loadRGBAImage(R.drawable.board_texture);
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
                    SAMPLE_TYPE_KEY_BIG_EYES, SAMPLE_TYPE_KEY_FACE_SLENDER -> {
                        val bitmap: Bitmap = loadRGBAImage(R.drawable.yifei)
                        mGLSurfaceView!!.setAspectRatio(bitmap.width, bitmap.height)
                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
                    }
//                    SAMPLE_TYPE_KEY_BIG_HEAD, SAMPLE_TYPE_KEY_ROTARY_HEAD -> {
//                        val b: Bitmap = loadRGBAImage(R.drawable.huge)
//                        mGLSurfaceView!!.setAspectRatio(b.width, b.height)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_KEY_VISUALIZE_AUDIO -> {
//                        if (mAudioCollector == null) {
//                            mAudioCollector = AudioCollector()
//                            mAudioCollector.addCallback(this@MainActivity)
//                            mAudioCollector.init()
//                        }
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                        val b1: Bitmap = loadRGBAImage(R.drawable.yifei)
//                        mGLSurfaceView!!.setAspectRatio(b1.width, b1.height)
//                    }
//                    SAMPLE_TYPE_KEY_SCRATCH_CARD -> {
//                        val b1: Bitmap = loadRGBAImage(R.drawable.yifei)
//                        mGLSurfaceView!!.setAspectRatio(b1.width, b1.height)
//                    }
//                    SAMPLE_TYPE_KEY_AVATAR -> {
//                        val b2: Bitmap = loadRGBAImage(R.drawable.avatar_a, 0)
//                        mGLSurfaceView!!.setAspectRatio(b2.width, b2.height)
//                        loadRGBAImage(R.drawable.avatar_b, 1)
//                        loadRGBAImage(R.drawable.avatar_c, 2)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_KEY_SHOCK_WAVE -> {
//                        val b3: Bitmap = loadRGBAImage(R.drawable.lye)
//                        mGLSurfaceView!!.setAspectRatio(b3.width, b3.height)
//                        mGLSurfaceView!!.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
//                    }
//                    SAMPLE_TYPE_KEY_MRT, SAMPLE_TYPE_KEY_FBO_BLIT -> {
//                        val b4: Bitmap = loadRGBAImage(R.drawable.lye)
//                        mGLSurfaceView!!.setAspectRatio(b4.width, b4.height)
//                    }
//                    else -> {
//                    }

                }
                mGLSurfaceView?.requestRender()
//                if (sampleType != SAMPLE_TYPE_KEY_VISUALIZE_AUDIO && mAudioCollector != null) {
//                    mAudioCollector.unInit()
//                    mAudioCollector = null
//                }
                dialog.cancel()
            }
        })
        resolution_list_view.layoutManager =
            LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        resolution_list_view.setAdapter(myPreviewSizeViewAdapter)
        resolution_list_view.scrollToPosition(mSampleSelectedIndex)


    }

    private fun loadRGBAImage(resId: Int): Bitmap {
        val inputStream = resources.openRawResource(resId)

        val bm: Bitmap

        try {
            bm = BitmapFactory.decodeStream(inputStream)
            if (bm != null) {
                val bytes: Int = bm.byteCount
                val buf = ByteBuffer.allocate(bytes)
                bm.copyPixelsToBuffer(buf)
                val byteArray = buf.array()
                mGLRender.setImageData(
                    IMAGE_FORMAT_RGBA,
                    bm.width,
                    bm.height,
                    byteArray
                )
            }
        } finally {
            try {
                inputStream.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return bm

    }

    protected fun hasPermissionsGranted(permissions: Array<String>): Boolean {
        for (permission in permissions) {
            if (ActivityCompat.checkSelfPermission(this, permission!!)
                != PackageManager.PERMISSION_GRANTED
            ) {
                return false
            }
        }
        return true
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String?>,
        grantResults: IntArray
    ) {
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (!hasPermissionsGranted(REQUEST_PERMISSIONS)) {
                Toast.makeText(
                    this,
                    "We need the permission: WRITE_EXTERNAL_STORAGE",
                    Toast.LENGTH_SHORT
                ).show()
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {

    }

    override fun onSensorChanged(event: SensorEvent?) {

    }

    override fun onDestroy() {
        super.onDestroy()
        mGLRender.unInit()
        /*
        * Once the EGL context gets destroyed all the GL buffers etc will get destroyed with it,
        * so this is unnecessary.
        * */
    }

}